<?php
// $Id$

/**
 * @file
 * Converts output of the ventrilo_status program into a more usable form.
 */

/**
 * Parses the results of a ventrilo server status query.
 *
 * @param array $result Output of the ventrilo_status program.
 * 
 * @return array An array containing the status of a ventrilo server.
 * The 'server' array can contain the following fields:
 * - 'NAME' - Server name.
 * - 'PHONETIC' - Phonetic spelling of the server name.
 * - 'COMMENT*' - Server comment.
 * - 'AUTH' - Server authentication mode (0 = none, 1 = global password, 2 = user password).
 * - 'VOICECODEC' - Voice codec code.
 * - 'VOICEFORMAT' - Voice format code.
 * - 'MAXCLIENTS' - Maximum number of connected clients.
 * - 'UPTIME' - Server uptime, in seconds.
 * - 'PLATFORM*' - Server platform.
 * - 'VERSION*' - Server version.
 * - 'CHANNELCOUNT' - Number of channels.
 * - 'CHANNELFIELDS' - Channel field names.
 * - 'CLIENTCOUNT' - Number of connected clients.
 * - 'CLIENTFIELDS' - Client field names.
 * - 'ERROR' - Error message.
 *
 * The 'channels' array can contain the following fields:
 * - 'CID' - Channel ID.
 * - 'PID' - Channel parent ID.
 * - 'NAME' - Channel name.
 * - 'COMM' - Channel comment.
 * - 'PROT' - Specifies if the channel is password protected (0 = open to public, 1 =
 *   channel password, 2 = user authorization).
 *
 * The 'clients' array can contain the following fields:
 * - 'NAME' - User name.
 * - 'COMM' - User comment.
 * - 'CID' - Channel ID.
 * - 'ADMIN' - Specifies if the user is an administrator (0 or 1).
 * - 'PHAN' - Specifies if the user is a phantom (0 or 1).
 * - 'PING' - User ping.
 * - 'SEC' - Time connected, in seconds.
 *
 * * These keys may not always be present.
 */
function ventstatus_parse_result($result) {
  $keys = array();
  
  foreach($result as $line) {
    list($key, $value) = _ventstatus_get_keyvalue_pair($line);
    
    if ($key == 'CHANNEL') {
      $channel = _ventstatus_get_fields($value);
      
      $channel_id = $channel['CID'];
      unset($channel['CID']);
      
      $keys['channels'][$channel_id] = $channel;
    }
    else if ($key == 'CLIENT') {
      $client = _ventstatus_get_fields($value);
      
      // The official script from Flagship Industries suggests that there is a user id
      // field to use here, but the program doesn't seem to output it.
      $keys['clients'][] = $client;
    }
    else {
      $keys['server'][$key] = $value;
    }
  }
  
  return $keys;
}

/**
 * Helper function; Parses status output into key-value pairs.
 */
function _ventstatus_get_keyvalue_pair($line, $delim = ':') {
  // First occurance of the key-value delimiter.
  $pos = strpos($line, $delim);
  
  $key = substr($line, 0, $pos);
  $value = trim(substr($line, $pos + 1, strlen($line) - $pos - 1));
  
  // Decode keys that may contain a URL-encoded string.
  switch ($key) {
    // Channel and client fields
    case 'NAME':
    case 'COMM':
    // Server status fields
    case 'COMMENT':
    case 'VOICECODEC':
    case 'VOICEFORMAT':
    case 'PHONETIC':
    case 'PLATFORM':
    case 'VERSION':
      $value = preg_replace("/%([0-9A-Fa-f]{2})/e", "chr(hexdec('\\1'))", $value);
      $value = mb_convert_encoding($value, 'UTF-8', 'ASCII');
      break;
  }
  
  return array($key, $value);
}

/**
 * Helper function; Parses a field key (such as 'CHANNEL' and 'CLIENT') into an associative array.
 */
function _ventstatus_get_fields($field_str) {
  $fields = array();
  $field_pairs = explode(',', $field_str);
  
  foreach ($field_pairs as $field) {
    list($key, $value) = _ventstatus_get_keyvalue_pair($field, '=');
    $fields[$key] = $value;
  }
  
  return $fields;
}
